package org.rcy.framework.security.authentication.provider;

import org.rcy.framework.api.security.SecurityUser;
import org.rcy.framework.security.authentication.AbstractFormToken;
import org.rcy.framework.security.authentication.authenticator.FormAuthenticator;
import org.rcy.framework.security.exception.UserNotFoundException;
import org.rcy.framework.security.form.UsernameAssertion;
import org.rcy.framework.security.exception.Assertion;
import org.rcy.framework.security.principal.UserProvider;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;

public abstract class FormAuthenticationProvider extends AbstractAuthenticationProvider {
    private UserProvider userProvider;
    private FormAuthenticator formAuthenticator;

    public FormAuthenticationProvider(UserProvider userProvider) {
        this.userProvider = userProvider;
    }

    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        if (!this.supports(authentication.getClass())) {
            this.logger.error("Only AbstractFormToken is supported");
            throw new AuthenticationServiceException("Only AbstractFormToken is supported");
        } else {
            AbstractFormToken originalToken = (AbstractFormToken)authentication;
            if (originalToken.getCredentials() == null) {
                this.logger.warn("Authentication failed: no credentials provided");
                throw new BadCredentialsException("Bad credentials:no credentials provided");
            } else {
                String username = originalToken.getName();
                Assertion assertion = new UsernameAssertion(username);
                SecurityUser user = this.loadUser(assertion);
                if (user == null) {
                    this.logger.warn("User Not Found:{}", assertion);
                    throw new UserNotFoundException("User Not Found!");
                } else {
                    this.formAuthenticator.authenticate(originalToken, user);
                    return this.createSuccessAuthentication(this.loadFinalUser(user), originalToken);
                }
            }
        }
    }

    public UserProvider getUserProvider() {
        return this.userProvider;
    }

    public FormAuthenticator getFormAuthenticator() {
        return this.formAuthenticator;
    }

    public void setFormAuthenticator(FormAuthenticator formAuthenticator) {
        this.formAuthenticator = formAuthenticator;
    }
}
